Repository navigation
superseded_by follows a chain of TAKEOVERs to its last link, so one lane holds the object (#74) - #204
Merged
Merged
Conversation
…ane holds the object (#74) Issue #30's dead-lane exception (PR #61) lets a TAKEOVER displace an earlier TAKEOVER: A claims, B takes over from A, C takes over from B once B is dead. superseded_by and lane_objects both asked only "does some other lane's last line here read TAKEOVER", so B's stale TAKEOVER was read as proof that C was displaced too. `who` reported zero holders of an object C held, `who --lane C` told C to release it, and `claim` granted the next lane a plain CLAIMED over it, as if the object were free. Every link that displaces a TAKEOVER names the lane it displaced as `← lane:<x>`: `claim --force` writes that payload for every hold that is not a CLAIMED. So a lane whose own last line is a TAKEOVER is now displaced only by another lane's standing TAKEOVER that names it, and not by one its own TAKEOVER names back. Any other open verb is displaced by any standing TAKEOVER, as before, and the taker named is the one no other standing TAKEOVER names, which is the lane that holds the object now. lane_objects applies the same rule, so `who --lane` and lane-end agree with `who`. The same one-hop test made two takers of one stale claim displace each other, so `who` called the object FREE. The README's "Known, deliberate" paragraph has always said both are holders, and with this change both are again. The suite's pinned ZERO for repoL-6 is now exactly one holder. New repoChain fixtures cover a three-link chain whose third link `claim --force` makes, the race (two holders, and --force refused), and two TAKEOVERs naming each other. README-lanes.md describes the rule. It also notes that the lanes-index `holds` view still applies the one-hop rule. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reviewer's GuideThis PR fixes takeover-chain state derivation by making Sequence diagram for force-claim takeover-chain resolutionsequenceDiagram
actor User
participant Claim as claim --force
participant Logs as Lane logs
participant Who as who
User->>Claim: claim object
Claim->>Logs: read each lane's last line
Claim->>Logs: write TAKEOVER ← lane:repoChain-3
User->>Who: inspect object
Who->>Logs: follow TAKEOVER links
Logs-->>Who: repoChain-4 is the sole holder
Who-->>User: HELD by repoChain-4
Flow diagram for takeover-chain holder resolutionflowchart LR
A["A: CLAIMED"] -->|TAKEOVER ← lane:A| B["B: TAKEOVER"]
B -->|TAKEOVER ← lane:B| C["C: TAKEOVER"]
B -. superseded by named link .-> X["B is displaced"]
C --> H["C is the sole holder"]
A -. stale earlier line .-> S["A and B are superseded"]
Flow diagram for ambiguous takeover conflictsflowchart LR
R["Stale claim"] --> A["TAKEOVER ← lane:A"]
R --> B["TAKEOVER ← lane:A"]
A --> H1["A is a holder"]
B --> H2["B is a holder"]
H1 --> C["who reports HELD by 2 lanes"]
H2 --> C
File-Level Changes
Assessment against linked issues
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
…tests this PR on today's main Main moved 15 commits past this branch's base f87fd5a, through the suite's machinery and pin (.github/workflows/tests.yml, contracts/openreposhape-pin.yaml, tests/conftest.py, tests/test_repo_hygiene.py, upstream/openRepoShape), after this PR's last green run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tests this PR on today's main Main moved 4 commits past this branch's base 2cb14a9, through the suite's machinery and pin (), after this PR's last green run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
brettheap
marked this pull request as ready for review
October 18, 2026 15:53
|
Sorry @brettheap, you've used your own review budget of 250,000 diff characters for the last 7 days. You can request another review in 2 days and 4 hours by commenting |
brettheap
added a commit
that referenced
this pull request
Oct 18, 2026
…so a migrated PAUSED row stops showing NO LOG (#89) (#206) Landed on Brett Heap's word "land #204 #206 #208 #218 #220 #221 when green" (2026-10-18), by lane openRepoTools-5. Required Linux CI (guard-launch-mode, tests, tests-no-submodule; run 39137733527) was green on head cd3ced0 with main 586dea2 in its tree. Main 0a49697 merged with head cd3ced0 is tree f88c2f1, which queue run 39137981522 (workflow_dispatch of tests on 3f5f4b9) tested whole and green. Independent review (lane 5, Opus, of 00b75e6; the merges of main add nothing to the PR's diff): LAND. Brett Heap confirmed the unpickable (row) lanes as built (2026-10-18). Closes #89 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
brettheap
added a commit
that referenced
this pull request
Oct 18, 2026
…or binding log instead of guessing a branch (#60) (#208) Landed on Brett Heap's word "land #204 #206 #208 #218 #220 #221 when green" (2026-10-18), by lane openRepoTools-5. Required Linux CI (guard-launch-mode, tests, tests-no-submodule; run 39137741203) was green on head 3edaf0a with main 586dea2 in its tree. Main be82c20 merged with head 3edaf0a is tree cfd2ee6, which queue run 39137988005 (workflow_dispatch of tests on 9db4863) tested whole and green. Independent review (lane 5, Opus, of c252a3c; the merges of main add nothing to the PR's diff): LAND. Closes #60 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
brettheap
added a commit
that referenced
this pull request
Oct 18, 2026
…s why refuse it before writing, and the deferred lane-start command keeps --agent (#85, #72 items 5, 6) (#218) Landed on Brett Heap's word "land #204 #206 #208 #218 #220 #221 when green" (2026-10-18), by lane openRepoTools-5. Required Linux CI (guard-launch-mode, tests, tests-no-submodule; run 39137747959) was green on head bfc5ddd with main 586dea2 in its tree. Main fca60f5 merged with head bfc5ddd is tree b188309, which queue run 39137992777 (workflow_dispatch of tests on 586df3b) tested whole and green. Independent review (lane 5, Opus, of 99f3853; the merges of main add nothing to the PR's diff): LAND. Brett Heap confirmed refusing CR/LF at the door (2026-10-18). Part of #85. Part of #72 (items 5-6). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
brettheap
added a commit
that referenced
this pull request
Oct 18, 2026
…ane-handoff renames the window only once the handoff can no longer be refused (#80 slices B and C) (#220) Landed on Brett Heap's word "land #204 #206 #208 #218 #220 #221 when green" (2026-10-18), by lane openRepoTools-5. Required Linux CI (guard-launch-mode, tests, tests-no-submodule; run 39137756635) was green on head 0b531e5 with main 586dea2 in its tree. Main 01eff2c merged with head 0b531e5 is tree a388312, which queue run 39137998354 (workflow_dispatch of tests on f335793) tested whole and green. Independent review (lane 5, Opus, of 9f6fd2d; the merges of main add nothing to the PR's diff): LAND. Brett Heap confirmed the rename trade as built (2026-10-18). Part of #80 (slices B and C). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
brettheap
added a commit
that referenced
this pull request
Oct 18, 2026
…ession ids, so the dead-lane --force check and duplicate-holder fail closed (#67) (#221) Landed on Brett Heap's word "land #204 #206 #208 #218 #220 #221 when green" (2026-10-18), by lane openRepoTools-5. Required Linux CI (guard-launch-mode, tests, tests-no-submodule; run 39137764839) was green on head 14696c7 with main 586dea2 in its tree. Main be0743b merged with head 14696c7 is tree 0052eff, which queue run 39138003629 (workflow_dispatch of tests on 147cbf6) tested whole and green. Independent review (lane 5, Opus, of fbd2bb1; the merges of main add nothing to the PR's diff): LAND. Closes #67 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



What was wrong
Issue #30's dead-lane exception (PR #61) lets a
TAKEOVERdisplace an earlierTAKEOVER: A claims, B takes over from A, and C takes over from B once B is dead.superseded_by, and its inline copy inlane_objects, asked only "does some other lane's last line here readTAKEOVER". So B's staleTAKEOVERwas read as proof that C was displaced too.Evidence: I ran
lanes-edit.shat f87fd5a against a throwaway workspace (LANES_NO_GIT=1,LANES_NO_GITHUB=1, a tempHOME). The logs were the issue's shape: repoZ-5 dead withTAKEOVER … ← lane:repoZ-0, then repoZ-6 withTAKEOVER … ← lane:repoZ-5.The same bug has three consequences at f87fd5a, each reproduced by the suite's new fixtures:
claimgrants a plainCLAIMEDover a held object. On a chain whose last link is dead,claim --forcefound no holder and wroteCLAIMED — lane repoChain-4 … opensoft/repoChain#1, not a takeover. Rule 1 exists to prevent exactly this outcome.who --laneandlane-endmisdirect the true holder. They told the true holder it had been "taken over" by the lane it took the object from, and handed it the release that would free the object.whocalled the object FREE, whiledocs/README-lanes.md("Known, deliberate") has always said both are holders. That text dates from The --help sentence naming what --install places beside this file reads like it's missing a word #3; the gate that made aTAKEOVERdisplaceable came with claim --force takes over a dead lane's hold; lane-end --retire ends a duplicate holder #61.What changed
Every link that displaces a
TAKEOVERnames the lane it displaced as← lane:<x>.claim --forcewrites that payload for every hold that is not aCLAIMED, and a comment URL is only ever the payload for aCLAIMEDtaken over. The rule now depends on the lane's own last line:TAKEOVER. It is displaced only by another lane's standingTAKEOVERthat names this lane, and not by one this lane's ownTAKEOVERnames back. So B is displaced by C and C by nothing: one lane holds the object, the chain's last link.TAKEOVER, as before. The taker named is one no other standingTAKEOVERnames, i.e. the lane that holds the object now, so A's line says C, not B.TAKEOVERs naming each other are both holders as well. No file order says which came last, so the conflict is shown instead of reported as FREE.lane_objectsapplies the same rule, sowho --laneandlane-endagree withwho. The stale-CLAIMED path that pays a comment URL needs nothing: a URL only ever displaces aCLAIMED, never aTAKEOVER, so it is never a link a chain is followed by. R18 is unchanged: a taker that has released no longer displaces anyone. The single-hop shapes the suite already covers give the same answers as before.Functions and regions edited:
lanes-edit.sh: lane_objects(other-lane block andEND, lines 3422-3466)lanes-edit.sh: superseded_by(its header comment and awk, lines 3495-3557)tests/test_lane_helpers.sh: seed rows(repoChain-1..4, afterrepoL-6's row)tests/test_lane_helpers.sh: seeded object logs(repoChain-1/2/3, afterrepoL-5's log)tests/test_lane_helpers.sh: the #30 dead-lane takeover block(repoL-6's pinned assertions, and the newrepoChaincases after it)docs/README-lanes.md: "State is per lane"(the superseded_by reports zero holders for a chain of two dead-lane TAKEOVERs on one object #74 paragraph replaced by the rule, and "Known, deliberate")docs/README-lanes.md: the index schema table,holds(a VIEW) rowTests
repoL-6's pinned assertions are flipped. The block that pinned ZERO holders as the known superseded_by reports zero holders for a chain of two dead-lane TAKEOVERs on one object #74 gap now expects exactly oneHOLDS,repoL-6, withrepoL-5superseded byrepoL-6. It also checks thatwho --lane repoL-6does not say "taken over by".repoChain-1claims#1,repoChain-2takes it over fromrepoChain-1, andrepoChain-3fromrepoChain-2, all seeded and dead. ThenLANES_LANE=repoChain-4 claim opensoft/repoChain#1 --no-github --forcemust writeTAKEOVER … ← lane:repoChain-3.whomust report exactly oneHOLDS,repoChain-4, and each earlier link must be superseded by the link that names it.#2, twoTAKEOVERs namerepoChain-1. Expected: twoHOLDS,state HELD, andclaim --forcerefused with exit 2 ("is held by 2 lanes"), writing nothing.#3, twoTAKEOVERs name each other. Expected: twoHOLDS.Local proof that they fail before and pass after. I did not run the full suite locally, per AGENTS.md; CI's
testsjob is the record. I ran a scratch mini-suite instead. It extracts the suite's own text by line range: the helpersok/bad/is/has/hasnt/run, the new seed rows, the seeded logs, and the whole block fromrepoL-6's claim to the last new assertion. It runs that text in a temp workspace underenv -iwithLANES_NO_GIT=1 LANES_NO_GITHUB=1:A separate scratch harness drove
whoandwho --laneon nine shapes. Holder counts, before → after:TAKEOVERnaming its own laneclaim --forceover a deadTAKEOVERbash -npasses on both shell files.Known remainders (not fixed here)
lanes-indexholdsview still applies the one-hop rule. Evaluatingddl("sqlite", "")fromlanes-indexon an in-memory store returns no row for the two-link chain and none for the race, wherewhonow names the last link and both racers. Fixing it means changing the view's SQL to readref/payload. Existing SQLite stores also need aDROP VIEWfirst, becauseCREATE VIEW IF NOT EXISTSkeeps the old definition. That is a separate change to the indexer. The README'sholdsrow now says so, andtest_the_holds_view_answers_as_who_does(single-hop) is unaffected.← lane:<old>payload. That chain shows two holders (a visible conflict) and does not resolve.TAKEOVERs each naming the next still displaces all of them. Only the two-lane mutual case is handled.Closes #74
🤖 Generated with Claude Code
Summary by Sourcery
Make takeover resolution follow explicit lane links to the final holder while retaining ambiguous takeover conflicts as visible multi-holder states.
Bug Fixes:
Enhancements:
who,who --lane, andlane-endthrough the shared object-resolution logic.holdsview still uses the previous one-hop behavior.Documentation:
holdsview limitation.Tests: